<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="T8ZUb" id="T8ZUb"><span data-lake-id="u78df5b43" id="u78df5b43">典型回答</span></h1>
  <p data-lake-id="ua589c7f2" id="ua589c7f2"><span data-lake-id="uca4e3b37" id="uca4e3b37">在Spring框架中，Shutdown Hook（关闭钩子）是一种机制，用于在应用程序关闭时执行一些清理操作。</span></p>
  <p data-lake-id="u4061a57c" id="u4061a57c"><br></p>
  <p data-lake-id="u5be52039" id="u5be52039"><span data-lake-id="ud1f7e110" id="ud1f7e110">Spring会向JVM注册一个shutdown hook，在接收到关闭通知的时候，进行bean的销毁，容器的销毁处理等操作。</span></p>
  <p data-lake-id="u08c10e2a" id="u08c10e2a"><br></p>
  <p data-lake-id="u86b819e2" id="u86b819e2"><span data-lake-id="u0e2ba3a4" id="u0e2ba3a4">在Spring框架中，可以使用使用AbstractApplicationContext类或其子类来注册Shutdown Hook。这些类提供了一个registerShutdownHook()方法，用于将Shutdown Hook与应用程序上下文关联起来。</span></p>
  <p data-lake-id="u987c3375" id="u987c3375"><br></p>
  <p data-lake-id="uf6d32dc3" id="uf6d32dc3"><span data-lake-id="u91603390" id="u91603390">很多中间件的优雅上下线的功能（优雅停机），都是基于Spring的shutdown hook的机制实现的，比如Dubbo的优雅下线。</span></p>
  <p data-lake-id="u2a016479" id="u2a016479"><span data-lake-id="ueca575a3" id="ueca575a3">​</span><br></p>
  <p data-lake-id="uf9c73155" id="uf9c73155"><br></p>
  <p data-lake-id="ua7c9ff0e" id="ua7c9ff0e"><span data-lake-id="ub262d6ba" id="ub262d6ba">还有我们经常在Spring中使用的以下两种方式，其实都是基于shutdown hook实现的。如：</span></p>
  <p data-lake-id="ub4bdd354" id="ub4bdd354"><span data-lake-id="u4327c2b4" id="u4327c2b4">​</span><br></p>
  <p data-lake-id="u6d6a564a" id="u6d6a564a"><span data-lake-id="u9e508ed6" id="u9e508ed6">1、实现DisposableBean接口，实现destroy方法：</span></p>
  <p data-lake-id="uf6cae8f0" id="uf6cae8f0"><span data-lake-id="u7bc0e3ed" id="u7bc0e3ed">​</span><br></p>
  <pre lang="java"><code>
@Slf4j
@Component
public class HollisShutdownHook implements DisposableBean {

    @Override
    public void destroy() throws Exception {
        // 清理资源
    }

}
</code></pre>
  <p data-lake-id="uf1070548" id="uf1070548"><span data-lake-id="ucc31e207" id="ucc31e207">​</span><br></p>
  <p data-lake-id="ub84ab9ae" id="ub84ab9ae"><span data-lake-id="u4361df49" id="u4361df49">2、使用@PreDestroy注解</span></p>
  <p data-lake-id="uecac8587" id="uecac8587"><span data-lake-id="uc6870fa0" id="uc6870fa0">​</span><br></p>
  <pre lang="java"><code>
@Service
public class HollisBean {
    
    @PreDestroy
    public void cleanup() {
        // 执行清理逻辑
        System.out.println("Performing cleanup before bean destruction...");
        
        // 关闭资源、释放连接等
        // ...
    }
}
</code></pre>
  <p data-lake-id="u802d1450" id="u802d1450"><br></p>
  <p data-lake-id="u42905131" id="u42905131"><br></p>
  <p data-lake-id="u41eab6bf" id="u41eab6bf"><span data-lake-id="u4a50ef6d" id="u4a50ef6d">当然，我们也可以借助Spring的事件机制，来自己注册一个hook，如下：</span></p>
  <p data-lake-id="u707cab77" id="u707cab77"><span data-lake-id="u0f53cd5e" id="u0f53cd5e">​</span><br></p>
  <pre lang="java"><code>
@Component
public class HollisListener implements ApplicationListener&lt;ContextClosedEvent&gt; {

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        // 做容器关闭之前的清理工作
    }

}
</code></pre>
  <p data-lake-id="u912e8759" id="u912e8759"><span data-lake-id="u7828fbb7" id="u7828fbb7">​</span><br></p>
  <p data-lake-id="uc4ef6e88" id="uc4ef6e88"><span data-lake-id="u64106db9" id="u64106db9">可以实现ApplicationListener接口，监听 Spring 容器的关闭事件（ContextClosedEvent），来做一些特殊的处理。</span></p>
 </body>
</html>